home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / tiff / tools / tiffdither.c < prev    next >
C/C++ Source or Header  |  1992-03-26  |  6KB  |  232 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/tiffdither.c,v 1.11 92/03/27 14:50:00 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include "tiffio.h"
  31.  
  32. typedef unsigned char u_char;
  33. typedef unsigned short u_short;
  34. typedef unsigned long u_long;
  35.  
  36. #if defined(SYSV) || defined(THINK_C) || defined(applec) || defined(VMS)
  37. #define    bzero(dst,len)        memset(dst, 0, len)
  38. #endif
  39.  
  40. #define    CopyField(tag, v) \
  41.     if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
  42.  
  43. u_long    imagewidth;
  44. u_long    imagelength;
  45. int    threshold = 128;
  46.  
  47. usage()
  48. {
  49.     fprintf(stderr,
  50.         "usage: tiffdither [-f24op] [-t threshold] in.tif out.tif.\n");
  51.     exit(-1);
  52. }
  53.  
  54. /* 
  55.  * Floyd-Steinberg error propragation with threshold.
  56.  * This code is stolen from tiffmedian.
  57.  */
  58. static
  59. fsdither(in, out)
  60.     TIFF *in, *out;
  61. {
  62.     u_char *outline, *inputline, *inptr;
  63.     short *thisline, *nextline, *tmpptr;
  64.     register u_char    *outptr;
  65.     register short *thisptr, *nextptr;
  66.     register long i, j;
  67.     u_long imax, jmax;
  68.     int lastline, lastpixel;
  69.     int bit, outlinesize;
  70.  
  71.     imax = imagelength - 1;
  72.     jmax = imagewidth - 1;
  73.     inputline = (u_char *)malloc(TIFFScanlineSize(in));
  74.     thisline = (short *)malloc(imagewidth * sizeof (short));
  75.     nextline = (short *)malloc(imagewidth * sizeof (short));
  76.     outlinesize = TIFFScanlineSize(out);
  77.     outline = (u_char *) malloc(outlinesize);
  78.  
  79.     /*
  80.      * Get first line
  81.      */
  82.     if (TIFFReadScanline(in, inputline, 0, 0) <= 0)
  83.         return;
  84.     inptr = inputline;
  85.     nextptr = nextline;
  86.     for (j = 0; j < imagewidth; ++j)
  87.         *nextptr++ = *inptr++;
  88.     for (i = 1; i < imagelength; ++i) {
  89.         tmpptr = thisline;
  90.         thisline = nextline;
  91.         nextline = tmpptr;
  92.         lastline = (i == imax);
  93.         if (TIFFReadScanline(in, inputline, i, 0) <= 0)
  94.             break;
  95.         inptr = inputline;
  96.         nextptr = nextline;
  97.         for (j = 0; j < imagewidth; ++j)
  98.             *nextptr++ = *inptr++;
  99.         thisptr = thisline;
  100.         nextptr = nextline;
  101.         bzero(outptr = outline, outlinesize);
  102.         bit = 0x80;
  103.         for (j = 0; j < imagewidth; ++j) {
  104.             register int v;
  105.  
  106.             lastpixel = (j == jmax);
  107.             v = *thisptr++;
  108.             if (v < 0)
  109.                 v = 0;
  110.             else if (v > 255)
  111.                 v = 255;
  112.             if (v > threshold) {
  113.                 *outptr |= bit;
  114.                 v -= 255;
  115.             }
  116.             bit >>= 1;
  117.             if (bit == 0) {
  118.                 outptr++;
  119.                 bit = 0x80;
  120.             }
  121.             if (!lastpixel)
  122.                 thisptr[0] += v * 7 / 16;
  123.             if (!lastline) {
  124.                 if (j != 0)
  125.                     nextptr[-1] += v * 3 / 16;
  126.                 *nextptr++ += v * 5 / 16;
  127.                 if (!lastpixel)
  128.                     nextptr[0] += v / 16;
  129.             }
  130.         }
  131.         if (TIFFWriteScanline(out, outline, i-1, 0) < 0)
  132.             break;
  133.     }
  134.     free(inputline);
  135.     free(thisline);
  136.     free(nextline);
  137.     free(outline);
  138. }
  139.  
  140. main(argc, argv)
  141.     int argc;
  142.     char *argv[];
  143. {
  144.     TIFF *in, *out;
  145.     u_short samplesperpixel, bitspersample = 1, shortv, config;
  146.     float floatv;
  147.     char thing[1024];
  148.     long rowsperstrip;
  149.     int c, compression = COMPRESSION_LZW;
  150.     int onestrip = 0;
  151.     int fillorder = FILLORDER_LSB2MSB;
  152.     long group3options = GROUP3OPT_FILLBITS;
  153.     extern int optind;
  154.     extern char *optarg;
  155.  
  156.     while ((c = getopt(argc, argv, "t:f24ops")) != -1)
  157.         switch (c) {
  158.         case 't':
  159.             threshold = atoi(optarg);
  160.             if (threshold < 0)
  161.                 threshold = 0;
  162.             else if (threshold > 255)
  163.                 threshold = 255;
  164.             break;
  165.         case 'f':        /* CCITT Group 3 */
  166.             compression = COMPRESSION_CCITTFAX3;
  167.             onestrip = 1;
  168.             break;
  169.         case '4':        /* CCITT Group 4 */
  170.             compression = COMPRESSION_CCITTFAX4;
  171.             onestrip = 1;
  172.             break;
  173.         case 'o':        /* reverse bit ordering in output */
  174.             fillorder = FILLORDER_LSB2MSB;
  175.             break;
  176.         case '2':        /* 2d-encoding */
  177.             group3options |= GROUP3OPT_2DENCODING;
  178.             break;
  179.         case 'p':        /* zero pad scanlines before EOL */
  180.             group3options &= ~GROUP3OPT_FILLBITS;
  181.             break;
  182.         case '?':
  183.             usage();
  184.             /*NOTREACHED*/
  185.         }
  186.     if (argc - optind < 2)
  187.         usage();
  188.     in = TIFFOpen(argv[optind], "r");
  189.     if (in == NULL)
  190.         exit(-1);
  191.     TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
  192.     if (samplesperpixel != 1) {
  193.         fprintf(stderr, "%s: Not a b&w image.\n", argv[0]);
  194.         exit(-1);
  195.     }
  196.     TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample);
  197.     if (bitspersample != 8) {
  198.         fprintf(stderr,
  199.             " %s: Sorry, only handle 8-bit samples.\n", argv[0]);
  200.         exit(-1);
  201.     }
  202.     out = TIFFOpen(argv[optind+1], "w");
  203.     if (out == NULL)
  204.         exit(-1);
  205.     CopyField(TIFFTAG_IMAGEWIDTH, imagewidth);
  206.     TIFFGetField(in, TIFFTAG_IMAGELENGTH, &imagelength);
  207.     TIFFSetField(out, TIFFTAG_IMAGELENGTH, imagelength-1);
  208.     TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
  209.     TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
  210.     TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  211.     TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
  212.     TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
  213.     TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
  214.     sprintf(thing, "Dithered B&W version of %s", argv[optind]);
  215.     TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, thing);
  216.     CopyField(TIFFTAG_ORIENTATION, shortv);
  217.     CopyField(TIFFTAG_XRESOLUTION, floatv);
  218.     CopyField(TIFFTAG_YRESOLUTION, floatv);
  219.     CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
  220.     if (onestrip)
  221.         rowsperstrip = imagelength-1;
  222.     else
  223.         rowsperstrip = (8*1024)/TIFFScanlineSize(out);
  224.     TIFFSetField(out, TIFFTAG_ROWSPERSTRIP,
  225.         rowsperstrip == 0 ? 1 : rowsperstrip);
  226.     if (compression == COMPRESSION_CCITTFAX3 && group3options)
  227.         TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, group3options);
  228.     fsdither(in, out);
  229.     TIFFClose(in);
  230.     TIFFClose(out);
  231. }
  232.